package ratelimit

import (
	"strconv"
	"strings"
	"sync"

	"baseService/internal/infrastructure/config"
	"baseService/internal/pkg/logger"
	"baseService/internal/pkg/response"

	"github.com/gin-gonic/gin"
	"golang.org/x/time/rate"
)

// Middleware 限流中间件（简化版）
// 对于中小项目，一个全局限流器就够了，不需要IP级、用户级、API级等复杂功能
type Middleware struct {
	config  *config.RateLimitConfig
	logger  logger.Logger
	limiter *rate.Limiter
	mu      sync.RWMutex
}

// NewMiddleware 创建限流中间件
func NewMiddleware(config *config.RateLimitConfig, logger logger.Logger) *Middleware {
	return &Middleware{
		config:  config,
		logger:  logger,
		limiter: rate.NewLimiter(rate.Limit(config.Rate), config.Burst),
	}
}

// Handler 中间件处理函数
func (m *Middleware) Handler() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 如果未启用，直接通过
		if !m.config.Enable {
			c.Next()
			return
		}

		// 检查是否在跳过路径中
		if m.shouldSkipPath(c.Request.URL.Path) {
			c.Next()
			return
		}

		// 检查限流
		if !m.limiter.Allow() {
			m.logger.Warnf("请求被限流 - path: %s, ip: %s", c.Request.URL.Path, c.ClientIP())

			// 设置Retry-After头
			c.Header("Retry-After", "1")
			c.Header("X-RateLimit-Limit", strconv.Itoa(m.config.Rate))
			c.Header("X-RateLimit-Remaining", "0")

			response.TooManyRequests(c)
			c.Abort()
			return
		}

		c.Next()
	}
}

// shouldSkipPath 检查是否应该跳过该路径
func (m *Middleware) shouldSkipPath(path string) bool {
	for _, skipPath := range m.config.SkipPaths {
		if path == skipPath {
			return true
		}
		// 简单的通配符匹配
		if strings.HasSuffix(skipPath, "*") {
			prefix := strings.TrimSuffix(skipPath, "*")
			if strings.HasPrefix(path, prefix) {
				return true
			}
		}
	}
	return false
}

// UpdateConfig 动态更新配置
func (m *Middleware) UpdateConfig(config *config.RateLimitConfig) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.config = config
	m.limiter = rate.NewLimiter(rate.Limit(config.Rate), config.Burst)
	m.logger.Infof("限流配置已更新 - rate: %d, burst: %d", config.Rate, config.Burst)
}

// GetStats 获取限流统计信息
func (m *Middleware) GetStats() map[string]interface{} {
	m.mu.RLock()
	defer m.mu.RUnlock()

	return map[string]interface{}{
		"enabled":    m.config.Enable,
		"rate":       m.config.Rate,
		"burst":      m.config.Burst,
		"skip_paths": m.config.SkipPaths,
	}
}
